/*
 * SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD
 *
 * SPDX-License-Identifier: CC0-1.0
 */
#if 0
#include "hello_world_main.h"
#include "socket.h"
#include "gatts_table_creat_demo.h" //ble蓝牙
#include "wifi.h"                   //WIFI
#include "zhongduan.h"              //中断
#include "zhi_xing.h"

static const char *TAG = "example1";
#define led_pin GPIO_NUM_2
#define led_deng_dai GPIO_NUM_12
// 多线程,定义消息缓冲区句柄
MessageBufferHandle_t xMessageBuffer; // 此为全局变量,蓝牙传递消息需要使用
MessageBufferHandle_t socketBufferQ;
static const size_t xMessageBufferSizeBytes = 100; // 消息缓冲区长度

/*LEDPWM初始化*/
void led_pwm_Config()
{
    ledc_timer_config_t ledc_timer_Structure;
    ledc_timer_Structure.speed_mode = LEDC_HIGH_SPEED_MODE;
    ledc_timer_Structure.timer_num = LEDC_TIMER_0;
    ledc_timer_Structure.duty_resolution = 13; // 分辨率
    ledc_timer_Structure.freq_hz = 5000;
    ledc_timer_Structure.clk_cfg = LEDC_APB_CLK;
    ledc_timer_config(&ledc_timer_Structure);
    ledc_channel_config_t ledc_channel_Structure;
    ledc_channel_Structure.gpio_num = led_deng_dai; // gpio 12
    ledc_channel_Structure.speed_mode = LEDC_HIGH_SPEED_MODE;
    ledc_channel_Structure.channel = LEDC_CHANNEL_0;
    ledc_channel_Structure.intr_type = LEDC_INTR_DISABLE;
    ledc_channel_Structure.timer_sel = 0;
    ledc_channel_Structure.duty = 0;
    ledc_channel_Structure.hpoint = 0;
    ledc_channel_config(&ledc_channel_Structure);
    // 若想改变占空比，用这个。
    // ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0, 8190 * 0.4); // 负占空比，负值为50/256=19.5%; 0-8190
    // ledc_update_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0);
}
/*发送LEDPWM方波*/
void ledPwmTianYao(float zhanKongBi) // zhanKongBi = 0.1到1之间
{
    ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0, 8190 * zhanKongBi); // 负占空比，负值为50/256=19.5%; 0-8190
    ledc_update_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0);
}

#if 0
// 多线程,创建队列并发布值的任务
void vATask(void *pvParameters)
{
    size_t xBytesSent;
    uint8_t ucArrayToSend[] = {'0', '1', '2', '3', 0};
    // unsigned char
    char *pcStringToSend = "String to send";
    const TickType_t x100ms = pdMS_TO_TICKS(100); // 延时100ms

    while (1)
    { // 消息缓存区发送的第一种方式
         // 将数组发送到消息缓冲区，最多阻塞 100 毫秒，以等待消息缓冲区中有足够的可用空间。
         xBytesSent = xMessageBufferSend(xMessageBuffer, (void *)ucArrayToSend, sizeof(ucArrayToSend), x100ms);

         if (xBytesSent != sizeof(ucArrayToSend))
         {
             // 在缓冲区中有足够的空间用于写入数据之前，对 xMessageBufferSend() 的调用超时。
         }

         // 消息缓存区发送的第二种方式
         //  将字符串发送到消息缓冲区。如果缓冲区空间不足，则立即返回。strlen 计算字符串长度不含结尾"\0"
         xBytesSent = xMessageBufferSend(xMessageBuffer, (void *)pcStringToSend, strlen(pcStringToSend), 0);
         if (xBytesSent != strlen(pcStringToSend))
         {
         }
         

         vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
}
#endif


// GPIO初始化
void gpioInit(void)
{
    gpio_reset_pin(led_pin); // 清除 GPIO 默认的状态
    gpio_reset_pin(led_deng_dai);
    // gpio_pad_select_gpio(GPIO_NUM_22);

    gpio_set_direction(led_pin, GPIO_MODE_OUTPUT);            // GPIO 输出模式
    gpio_set_direction(led_deng_dai, GPIO_MODE_INPUT_OUTPUT); // GPIO 输出模式
}
void xin_pian_xin_xi() // 打印芯片信息
{
    /* *******************打印芯片信息*********** */
    esp_chip_info_t chip_info;
    uint32_t flash_size;
    esp_chip_info(&chip_info);
    printf("This is %s chip with %d CPU core(s), %s%s%s%s, ",
           CONFIG_IDF_TARGET,
           chip_info.cores,
           (chip_info.features & CHIP_FEATURE_WIFI_BGN) ? "WiFi/" : "",
           (chip_info.features & CHIP_FEATURE_BT) ? "BT" : "",
           (chip_info.features & CHIP_FEATURE_BLE) ? "BLE" : "",
           (chip_info.features & CHIP_FEATURE_IEEE802154) ? ", 802.15.4 (Zigbee/Thread)" : "");

    unsigned major_rev = chip_info.revision / 100;
    unsigned minor_rev = chip_info.revision % 100;
    printf("silicon revision v%d.%d, ", major_rev, minor_rev);
    if (esp_flash_get_size(NULL, &flash_size) != ESP_OK)
    {
        printf("Get flash size failed");
        return;
    }

    printf("%" PRIu32 "MB %s flash\n", flash_size / (uint32_t)(1024 * 1024),
           (chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded" : "external");

    printf("Minimum free heap size: %" PRIu32 " bytes\n", esp_get_minimum_free_heap_size());
    /***************** 打印芯片信息******** */
}

bool jian_la_huan_chong_qu()//以动态分配内存的方式建立消息缓冲区
{
    // 以动态分配内存的方式建立消息缓冲区
    xMessageBuffer = xMessageBufferCreate(xMessageBufferSizeBytes);
    socketBufferQ = xMessageBufferCreate(xMessageBufferSizeBytes);
    if (socketBufferQ == NULL || xMessageBuffer == NULL)
    {
        printf("message Buffer Create fail!\n");
        return false;
    }
    else
    {
        printf("message Buffer Create successed!\n");
        return true;
    }
}

void app_main(void)
{
    xin_pian_xin_xi(); // 打印芯片信息
    gpioInit();        // GPIO初始化
    led_pwm_Config();  // pwm初始化
    jian_la_huan_chong_qu();

    /*xTaskCreate 建立新任务(线程)*/
    xTaskCreate(task_function, "task_functio", 1024 * 2, NULL, 12, NULL);
    xTaskCreate(vADifferentTask,   // 指向任务入口函数的指针。任务必须实现为永不返回（即连续循环），或者应该使用 vTaskDelete 函数终止
                "vADifferentTask", // 任务的描述性名称。这主要是为了*方便调试。configMAX_TASK_NAME_LEN 定义的最大长度 - 默认 * 为 16。
                1024 * 2,          // 任务堆栈的大小指定为 * 字节数。请注意，这与普通 FreeRTOS 不同。
                NULL,              // 将用作正在创建的任务的参数的指针。
                10,                // 任务应运行的优先级。
                NULL);             // 用于传回一个句柄，通过该句柄可以引用创建的任务

    app_bt_aa(); // 启动蓝牙

    char *ssid = "cccxxx";
    char *password = "chenxin1234567890";

    wifi_init(ssid, password); // 启动 WIFI

    zhong_duan_H(27);
    for (;;)
    {
        vTaskDelay(100 / portTICK_PERIOD_MS);
    }
    float zkb = 0;
    for (int i = 10; i >= 0; i--)
    {
        printf("Restarting in %d seconds...\n", i);
        vTaskDelay(1000 / portTICK_PERIOD_MS); // 定时器延时
        gpio_set_level(led_pin, 0);            // 输出低电平
        zkb = zkb + 0.1;

        if (i < 2)
        {
            i = 20;
        }
        if (zkb > 0.9)
        {
            zkb = 0.1;
        }

        vTaskDelay(1000 / portTICK_PERIOD_MS);
        gpio_set_level(led_pin, 1); // 输出高电平
        ESP_LOGI(TAG, "现在的占空比为: %f", zkb);
        ledPwmTianYao(zkb);
    }
    printf("Restarting now.\n");
    fflush(stdout); // 用于刷新标准输出流
    esp_restart();  // 重启
}
#elif 1
/*
 * SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD
 *
 * SPDX-License-Identifier: CC0-1.0
 */

#include "c3_main.h"
#include "socket.h"
#include "gatts_table_creat_demo.h" //ble蓝牙
#include "wifi.h"                   //WIFI
#include "zhongduan.h"              //中断
#include "zhi_xing.h"

static const char *TAG = "c3_main: ";
#define led_pin GPIO_NUM_2
#define led_deng_dai GPIO_NUM_20


// 多线程,定义消息缓冲区句柄
MessageBufferHandle_t xMessageBuffer; // 此为全局变量,蓝牙传递消息需要使用
MessageBufferHandle_t socketBufferQ;
static const size_t xMessageBufferSizeBytes = 256; // 消息缓冲区长度
bool wifi_switch_BQ = false;                       // 是否运行WIFI

/*LEDPWM初始化*/
void led_pwm_Config()
{
    ledc_timer_config_t ledc_timer = {
        .speed_mode = LEDC_HIGH_SPEED_MODE,
        .timer_num = LEDC_TIMER_0,
        .duty_resolution = LEDC_TIMER_13_BIT, // LEDC PWM 占空比分辨率为 13 位
        .freq_hz = (5000),                    // Set output frequency at 5 kHz
        .clk_cfg = LEDC_APB_CLK               // LEDC_AUTO_CLK
    };
    ESP_ERROR_CHECK(ledc_timer_config(&ledc_timer));

    // Prepare and then apply the LEDC PWM channel configuration
    ledc_channel_config_t ledc_channel = {
        .speed_mode = LEDC_HIGH_SPEED_MODE,
        .channel = LEDC_CHANNEL_0,
        .timer_sel = LEDC_TIMER_0,
        .intr_type = LEDC_INTR_DISABLE,
        .gpio_num = led_deng_dai,
        .duty = 0, // Set duty to 0%
        .hpoint = 0};
    ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel));

    /*
        ledc_timer_config_t ledc_timer_Structure;
        ledc_timer_Structure.speed_mode = LEDC_LOW_SPEED_MODE;//LEDC_HIGH_SPEED_MODE;
        ledc_timer_Structure.timer_num = LEDC_TIMER_0;
        ledc_timer_Structure.duty_resolution = 13; // 分辨率
        ledc_timer_Structure.freq_hz = 5000;
        ledc_timer_Structure.clk_cfg = LEDC_APB_CLK;
        ledc_timer_config(&ledc_timer_Structure);

        ledc_channel_config_t ledc_channel_Structure;
        ledc_channel_Structure.gpio_num = led_deng_dai; // gpio 12
        ledc_channel_Structure.speed_mode = LEDC_LOW_SPEED_MODE;
        ledc_channel_Structure.channel = LEDC_CHANNEL_0;
        ledc_channel_Structure.intr_type = LEDC_INTR_DISABLE;
        ledc_channel_Structure.timer_sel = 0;
        ledc_channel_Structure.duty = 0;
        ledc_channel_Structure.hpoint = 0;
        ledc_channel_config(&ledc_channel_Structure);
        */
    // 若想改变占空比，用这个。
    // ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0, 8190 * 0.4); // 负占空比，负值为50/256=19.5%; 0-8190
    // ledc_update_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_0);
}
/*发送LEDPWM方波*/
void ledPwmTianYao(float zhanKongBi) // zhanKongBi = 0.1到1之间
{
    // ledc_set_duty_and_update();
    // ledc_set_duty_with_hpoint();
    ESP_ERROR_CHECK(ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, 8190 * zhanKongBi)); // 负占空比，负值为50/256=19.5%; 0-8190
    ESP_ERROR_CHECK(ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0));
}

#if 0
// 多线程,创建队列并发布值的任务
void vATask(void *pvParameters)
{
    size_t xBytesSent;
    uint8_t ucArrayToSend[] = {'0', '1', '2', '3', 0};
    // unsigned char
    char *pcStringToSend = "String to send";
    const TickType_t x100ms = pdMS_TO_TICKS(100); // 延时100ms

    while (1)
    { // 消息缓存区发送的第一种方式
         // 将数组发送到消息缓冲区，最多阻塞 100 毫秒，以等待消息缓冲区中有足够的可用空间。
         xBytesSent = xMessageBufferSend(xMessageBuffer, (void *)ucArrayToSend, sizeof(ucArrayToSend), x100ms);

         if (xBytesSent != sizeof(ucArrayToSend))
         {
             // 在缓冲区中有足够的空间用于写入数据之前，对 xMessageBufferSend() 的调用超时。
         }

         // 消息缓存区发送的第二种方式
         //  将字符串发送到消息缓冲区。如果缓冲区空间不足，则立即返回。strlen 计算字符串长度不含结尾"\0"
         xBytesSent = xMessageBufferSend(xMessageBuffer, (void *)pcStringToSend, strlen(pcStringToSend), 0);
         if (xBytesSent != strlen(pcStringToSend))
         {
         }
         

         vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
}
#endif

// GPIO初始化
void gpioInit(void)
{
    gpio_reset_pin(led_pin); // 清除 GPIO 默认的状态
    gpio_reset_pin(led_deng_dai);
    // gpio_pad_select_gpio(GPIO_NUM_22);

    gpio_set_direction(led_pin, GPIO_MODE_OUTPUT);            // GPIO 输出模式
    gpio_set_direction(led_deng_dai, GPIO_MODE_INPUT_OUTPUT); // GPIO 输出模式
}
void xin_pian_xin_xi() // 打印芯片信息
{
    /* *******************打印芯片信息*********** */
    esp_chip_info_t chip_info;
    uint32_t flash_size;
    esp_chip_info(&chip_info);
    printf("This is %s chip with %d CPU core(s), %s%s%s%s, ",
           CONFIG_IDF_TARGET,
           chip_info.cores,
           (chip_info.features & CHIP_FEATURE_WIFI_BGN) ? "WiFi/" : "",
           (chip_info.features & CHIP_FEATURE_BT) ? "BT" : "",
           (chip_info.features & CHIP_FEATURE_BLE) ? "BLE" : "",
           (chip_info.features & CHIP_FEATURE_IEEE802154) ? ", 802.15.4 (Zigbee/Thread)" : "");

    unsigned major_rev = chip_info.revision / 100;
    unsigned minor_rev = chip_info.revision % 100;
    printf("silicon revision v%d.%d, ", major_rev, minor_rev);
    if (esp_flash_get_size(NULL, &flash_size) != ESP_OK)
    {
        printf("Get flash size failed");
        return;
    }

    printf("%" PRIu32 "MB %s flash\n", flash_size / (uint32_t)(1024 * 1024),
           (chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded" : "external");

    printf("Minimum free heap size: %" PRIu32 " bytes\r\n", esp_get_minimum_free_heap_size());
    ESP_LOGI(TAG, "芯片信息打印完毕\r\n");
    /***************** 打印芯片信息******** */
}

bool jian_la_huan_chong_qu() // 以动态分配内存的方式建立消息缓冲区
{
    // 以动态分配内存的方式建立消息缓冲区
    xMessageBuffer = xMessageBufferCreate(xMessageBufferSizeBytes);
    socketBufferQ = xMessageBufferCreate(xMessageBufferSizeBytes);
    if (socketBufferQ == NULL || xMessageBuffer == NULL)
    {
        ESP_LOGI(TAG, "huan chong qu jian li shi bai 001\n");
        return false;
    }
    else
    {
        ESP_LOGI(TAG, "huan chong qu jian li cheng gong 001\n");
        return true;
    }
}

void app_main(void)
{
    xin_pian_xin_xi();       // 打印芯片信息
    gpioInit();              // GPIO初始化
    led_pwm_Config();        // pwm初始化
    jian_la_huan_chong_qu(); // 建立缓冲区

    /*xTaskCreate 建立新任务(线程)*/
    xTaskCreate(task_function, "task_functio", 1024 * 2, NULL, 12, NULL);
    xTaskCreate(vADifferentTask,   // 指向任务入口函数的指针。任务必须实现为永不返回（即连续循环），或者应该使用 vTaskDelete 函数终止
                "vADifferentTask", // 任务的描述性名称。这主要是为了*方便调试。configMAX_TASK_NAME_LEN 定义的最大长度 - 默认 * 为 16。
                1024 * 2,          // 任务堆栈的大小指定为 * 字节数。请注意，这与普通 FreeRTOS 不同。
                NULL,              // 将用作正在创建的任务的参数的指针。
                10,                // 任务应运行的优先级。
                NULL);             // 用于传回一个句柄，通过该句柄可以引用创建的任务

    app_bt_aa();  // 启动蓝牙
    nvs_init();   // 初始化NVS功能
    wifi_Start(); // 启动WIFI
    zhong_duan_init();
    while (1)
    {
        vTaskDelay(5000 / portTICK_PERIOD_MS);
    }
#if 0
    float zkb = 0;
    for (int i = 10; i >= 0; i--)
    {
        printf("Restarting in %d seconds...\n", i);
        vTaskDelay(1000 / portTICK_PERIOD_MS); // 定时器延时  
        gpio_set_level(led_pin, 0);            // 输出低电平
        zkb = zkb + 0.1;

        if (i < 2)
        {
            i = 20;
        }
        if (zkb > 0.9)
        {
            zkb = 0.1;
        }

        vTaskDelay(1000 / portTICK_PERIOD_MS);
        gpio_set_level(led_pin, 1); // 输出高电平
        ESP_LOGI(TAG, "现在的占空比为: %f", zkb);
        ledPwmTianYao(zkb);
    }
    printf("Restarting now.\n");
    fflush(stdout); // 用于刷新标准输出流
    esp_restart();  // 重启
#endif
}

#endif